package com.sinosoft.dsp.platform.utils;

import javax.faces.application.FacesMessage;
import javax.faces.application.FacesMessage.Severity;
import javax.faces.component.UIComponent;
import javax.faces.context.ExternalContext;
import javax.faces.context.FacesContext;
import javax.servlet.ServletContext;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.primefaces.context.RequestContext;
import org.primefaces.json.JSONArray;
import org.primefaces.json.JSONException;
import org.primefaces.json.JSONObject;

import com.sinosoft.dsp.system.core.log.Log;
import com.sinosoft.dsp.system.utils.Const;

/**
 * 工具类，涉及到当前请求的直接访问或修改
 * 
 * @since 1.0 2010-4-14
 * @author 潘巍（Peter Pan）
 * 
 */
public class FacesContextUtils {

	private static final Log log = Log
			.getLog(FacesContextUtils.class.getName());

	public static final String MESSAGES_FLAG = "msgs";

	private static final java.lang.String SEVERITY_INFO_NAME = "INFO";
	private static final java.lang.String SEVERITY_WARN_NAME = "WARN";
	private static final java.lang.String SEVERITY_ERROR_NAME = "ERROR";
	private static final java.lang.String SEVERITY_FATAL_NAME = "FATAL";

	/**
	 * 工具方法：添加全局消息
	 * 
	 * @param severity
	 *            - 消息类型
	 * @param summary
	 *            - 要添加的消息
	 */
	public static void addGlobalFacesMessage(Severity severity, String summary) {
		addGlobalFacesMessage(severity, summary, summary);
	}

	/**
	 * 工具方法：添加全局消息
	 * 
	 * @param severity
	 *            - 消息类型
	 * @param summary
	 *            - 要添加的消息
	 * @param detail
	 *            - 要添加的详细描述
	 */
	public static void addGlobalFacesMessage(Severity severity, String summary,
			String detail) {
		FacesContext.getCurrentInstance().addMessage(null,
				addMessage(severity, summary, detail));
	}

	/**
	 * 工具方法：添加全局错误消息
	 * 
	 * @param summary
	 *            - 要添加的消息
	 */
	public static void addGlobalErrorFacesMessage(String summary) {
		addGlobalErrorFacesMessage(summary, summary);
	}

	/**
	 * 工具方法：添加全局错误消息
	 * 
	 * @param summary
	 *            - 要添加的消息
	 * @param detail
	 *            - 要添加的详细描述
	 */
	public static void addGlobalErrorFacesMessage(String summary, String detail) {
		FacesContext.getCurrentInstance().addMessage(null,
				addErrorMessage(summary, detail));
	}

	/**
	 * 工具方法：添加消息到指定组件
	 * 
	 * @param severity
	 *            - 消息类型
	 * @param componentId
	 *            - 组件标识
	 * @param summary
	 *            - 要添加的消息
	 */
	public static void addFacesMessage(Severity severity, String componentId,
			String summary) {
		addFacesMessage(severity, componentId, summary, summary);
	}

	/**
	 * 工具方法：添加消息到指定组件
	 * 
	 * @param severity
	 *            - 消息类型
	 * @param componentId
	 *            - 组件标识
	 * @param summary
	 *            - 要添加的消息
	 * @param detail
	 *            - 要添加的详细描述
	 */
	public static void addFacesMessage(Severity severity, String componentId,
			String summary, String detail) {
		UIComponent root = FacesContext.getCurrentInstance().getViewRoot();
		UIComponent component = root.findComponent(componentId);
		FacesContext.getCurrentInstance().addMessage(
				component.getClientId(FacesContext.getCurrentInstance()),
				new FacesMessage(severity, summary, detail));
	}

	/**
	 * 工具方法：添加错误消息到指定组件
	 * 
	 * @param componentId
	 *            - 组件标识
	 * @param summary
	 *            - 要添加的消息
	 */
	public static void addErrorFacesMessage(String componentId, String summary) {
		addErrorFacesMessage(componentId, summary, summary);
	}

	/**
	 * 工具方法：添加错误消息到指定组件
	 * 
	 * @param componentId
	 *            - 组件标识
	 * @param summary
	 *            - 要添加的消息
	 * @param detail
	 *            - 要添加的详细描述
	 */
	public static void addErrorFacesMessage(String componentId, String summary,
			String detail) {
		FacesContext.getCurrentInstance().validationFailed();
		addFacesMessage(FacesMessage.SEVERITY_ERROR, componentId, summary,
				detail);
	}

	/**
	 * 工具方法：创建消息
	 * 
	 * @param severity
	 *            - 消息类型
	 * @param summary
	 *            - 要添加的消息
	 * @param detail
	 *            - 要添加的详细描述
	 * @return
	 */
	public static FacesMessage addMessage(Severity severity, String summary) {
		return addMessage(severity, summary, summary);
	}

	/**
	 * 工具方法：创建消息
	 * 
	 * @param severity
	 *            - 消息类型
	 * @param summary
	 *            - 要添加的消息
	 * @param detail
	 *            - 要添加的详细描述
	 * @return
	 */
	public static FacesMessage addMessage(Severity severity, String summary,
			String detail) {
		if (!Const.isEmpty(summary)) {
			if (severity == null) {
				severity = FacesMessage.SEVERITY_INFO;
			}
			// 添加到反馈中
			RequestContext requestContext = RequestContext.getCurrentInstance();
			if (requestContext != null) {

				String em = (String) requestContext.getCallbackParams().get(
						MESSAGES_FLAG);

				JSONObject jo = null;
				try {
					if (em != null) {
						jo = new JSONObject(em);
					} else {
						jo = new JSONObject();
					}
				} catch (JSONException e) {
					jo = new JSONObject();
				}
				JSONArray ja = null;
				try {
					if (severity == FacesMessage.SEVERITY_INFO) {
						if (!jo.has(SEVERITY_INFO_NAME)) {
							jo.put(SEVERITY_INFO_NAME, new JSONArray());
						}
						ja = jo.optJSONArray(SEVERITY_INFO_NAME);
					} else if (severity == FacesMessage.SEVERITY_WARN) {
						if (!jo.has(SEVERITY_WARN_NAME)) {
							jo.put(SEVERITY_WARN_NAME, new JSONArray());
						}
						ja = jo.optJSONArray(SEVERITY_WARN_NAME);
					} else if (severity == FacesMessage.SEVERITY_ERROR) {
						if (!jo.has(SEVERITY_ERROR_NAME)) {
							jo.put(SEVERITY_ERROR_NAME, new JSONArray());
						}
						ja = jo.optJSONArray(SEVERITY_ERROR_NAME);
					} else if (severity == FacesMessage.SEVERITY_FATAL) {
						if (!jo.has(SEVERITY_FATAL_NAME)) {
							jo.put(SEVERITY_FATAL_NAME, new JSONArray());
						}
						ja = jo.optJSONArray(SEVERITY_FATAL_NAME);
					}
				} catch (JSONException e) {
				}
				ja.put(summary);
				requestContext.addCallbackParam(MESSAGES_FLAG, jo.toString());
			}
			// 创建消息
			return new FacesMessage(severity, summary, detail);
		}
		return null;
	}

	/**
	 * 工具方法：创建错误消息
	 * 
	 * @param summary
	 *            - 要添加的消息
	 * @return
	 */
	public static FacesMessage addErrorMessage(String summary) {
		return addErrorMessage(summary, summary);
	}

	/**
	 * 工具方法：创建错误消息
	 * 
	 * @param summary
	 *            - 要添加的消息
	 * @param detail
	 *            - 要添加的详细描述
	 * @return
	 */
	public static FacesMessage addErrorMessage(String summary, String detail) {
		if (!Const.isEmpty(summary)) {
			FacesContext.getCurrentInstance().validationFailed();
			return addMessage(FacesMessage.SEVERITY_ERROR, summary, detail);
		}
		return null;
	}

	/**
	 * 工具方法：获得当前ServletContext的引用
	 * 
	 * @return servlet的context对象
	 */
	public static ServletContext getServletContext() {
		return (ServletContext) getExternalContext().getContext();
	}

	/**
	 * 工具方法：获得当前ExternalContext的引用
	 * 
	 * @return external的content对象
	 */
	public static ExternalContext getExternalContext() {
		return FacesContext.getCurrentInstance().getExternalContext();
	}

	/**
	 * 工具方法：获得当前HTTPSession的引用
	 * 
	 * @return session对象
	 */
	public static HttpSession getSession() {
		return getSession(false);
	}

	public static HttpSession getSession(boolean create) {
		return (HttpSession) getExternalContext().getSession(create);
	}

	/**
	 * 工具方法：获得当前HttpServletRequest的引用
	 * 
	 * @return request对象
	 */
	public static HttpServletRequest getRequest() {
		return (HttpServletRequest) getExternalContext().getRequest();
	}

	/**
	 * 工具方法：获得当前HttpServletRequest中的参数值
	 * 
	 * @param key
	 *            键
	 * @return
	 */
	public static String getParameter(String key) {
		return getRequest().getParameter(key);
	}

	/**
	 * 工具方法：获得当前HttpServletRequest中的参数值
	 * 
	 * @param key
	 *            键
	 * @param def
	 *            默认值
	 * @return
	 */
	public static String getParameter(String key, String def) {
		String rtn = getRequest().getParameter(key);
		return Const.isJSEmpty(rtn) ? def : rtn;
	}

	/**
	 * 工具方法：获得当前HttpServletResponse的引用
	 * 
	 * @return
	 */
	public static HttpServletResponse getResponse() {
		return (HttpServletResponse) getExternalContext().getResponse();
	}

	/**
	 * 获得当前请求的Cookie值
	 * 
	 * @param key
	 * @return
	 */
	public static String getCookie(String key) {
		try {
			Cookie[] cookies = getRequest().getCookies();
			if (cookies != null) {
				for (Cookie c : cookies) {
					if (c.getName().equals(key)) {
						return c.getValue();
					}
				}
			}
		} catch (Exception e) {
			log.error("获得当前请求的Cookie值出现错误：" + e.getMessage());
		}
		return null;
	}

	/**
	 * 向当前响应中添加Cookie<br>
	 * 默认生命周期30天
	 * 
	 * @param key
	 * @param value
	 */
	public static void addCookie(String key, String value) {
		addCookie(key, value, 30 * 24 * 60 * 60);
	}

	/**
	 * 向当前响应中添加Cookie
	 * 
	 * @param key
	 * @param value
	 * @param second
	 *            最大生命周期(秒)
	 */
	public static void addCookie(String key, String value, int second) {
		try {
			Cookie cookie = new Cookie(key, value);
			cookie.setMaxAge(second);
			getResponse().addCookie(cookie);
		} catch (Exception e) {
			log.error("向当前响应中添加Cookie出现错误：" + e.getMessage());
		}
	}

	/**
	 * 向当前请求返回值域内添加属性值
	 * 
	 * @param key
	 * @param value
	 */
	public static void addCallbackParam(String key, Object value) {
		RequestContext requestContext = RequestContext.getCurrentInstance();
		requestContext.addCallbackParam(key, value);
	}
}
